
#include "Song.h"


Song::Song(SQLHDBC hdbc_, int id_) : hdbc(hdbc_), id(id_), loaded(false) {
    //pull data immediate to Song (title & comment), but do not populate list 
    // of Stanzas

    SQLRETURN rv;
	SQLHSTMT hstmt = SQL_NULL_HANDLE;

    RaiiSQLAllocHandle alloc(SQL_HANDLE_STMT, hdbc, &hstmt);
	rv = alloc.result();
	if(ODBC_FAILED(rv)) {
		display_diagnostics(SQL_HANDLE_STMT, hstmt);
		throw SqlException("Failed to allocate a statement handle");
	}

	stringstream squery;
	squery <<	"SELECT song_title, song_comment "
				"FROM song "
				"WHERE song_id = " << id;
	string query;
	getline(squery, query);

	rv = SQLExecDirect(hstmt, (SQLCHAR*)query.c_str(), SQL_NTS);

    if(ODBC_FAILED(rv)) {
		display_diagnostics(SQL_HANDLE_STMT, hstmt);
		throw SqlException("Failed to execute SQL statement");
	}
	
	SQLCHAR song_title[81];
	SQLINTEGER song_title_len;

	rv = SQLBindCol(hstmt, 1, SQL_C_CHAR, song_title, sizeof(song_title), &song_title_len);

	if(ODBC_FAILED(rv)) {
		display_diagnostics(SQL_HANDLE_STMT, hstmt);
		throw SqlException("Failed to bind column 1 (song_title)");
	}
	

	SQLCHAR song_comment[1001];
	SQLINTEGER song_comment_len;

	rv = SQLBindCol(hstmt, 2, SQL_C_CHAR, song_comment, sizeof(song_comment), &song_comment_len);

	if(ODBC_FAILED(rv)) {
		display_diagnostics(SQL_HANDLE_STMT, hstmt);
		throw SqlException("Failed to bind column 2 (song_comment)");
	}

	if((rv = SQLFetch(hstmt)) == SQL_NO_DATA || ODBC_FAILED(rv)) {
        display_diagnostics(SQL_HANDLE_STMT, hstmt);
		throw SqlException("Failed to fetch immediate song data");
	}

	title.assign(song_title, song_title_len);
	comment.assign(song_comment, song_comment_len);
}

Song::~Song() {
    clear();
}

void Song::load() {
    //populate list of Stanzas (allocate dynamically), but do not call load() 
    // on them

    
}

void Song::clear() {
    for(int i=0; i < data.size(); ++i) {
        data.at(i)->clear();
        delete data.at(i);
        data.at(i) = NULL;
    }

    Base::clear();
}


SongList::SongList(SQLHDBC hdbc_) : hdbc(hdbc_) {
    
}

SongList::~SongList() {
    clear();
}

void SongList::load() {
    //populate list of songs (allocate dynamically), but do not call load() 
    // on them

	SQLRETURN rv;
	SQLHSTMT hstmt = SQL_NULL_HANDLE;

    RaiiSQLAllocHandle alloc(SQL_HANDLE_STMT, hdbc, &hstmt);
	rv = alloc.result();
	if(ODBC_FAILED(rv)) {
		display_diagnostics(SQL_HANDLE_STMT, hstmt);
		throw SqlException("Failed to allocate a statement handle");
	}

    rv = SQLExecDirect(hstmt, (SQLCHAR*)
	            "SELECT song_id "
                "FROM song "
                "ORDER BY song_id", 
            SQL_NTS);

    if(ODBC_FAILED(rv)) {
		display_diagnostics(SQL_HANDLE_STMT, hstmt);
		throw SqlException("Failed to execute SQL statement");
	}

	SQLINTEGER song_id;
	SQLINTEGER dummy;

	rv = SQLBindCol(hstmt, 1, SQL_C_LONG, &stno, sizeof(stno), &dummy);

	if(ODBC_FAILED(rv)) {
		display_diagnostics(SQL_HANDLE_STMT, hstmt);
		throw SqlException("Failed to bind column 1 (song_id)");
	}
	

	while((rv = SQLFetch(hstmt)) != SQL_NO_DATA) {
		if(ODBC_FAILED(rv)) {
            display_diagnostics(SQL_HANDLE_STMT, hstmt);
		    throw SqlException("Failed to fetch data");
		}

		data.push_back(new Song(hdbc, song_id));
	}
}

void SongList::clear() {
    for(int i=0; i < data.size(); ++i) {
        data.at(i)->clear();
        delete data.at(i);
        data.at(i) = NULL;
    }

    Base::clear();
}

